package com.teacher.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.teacher.common.CommonResult;
import com.teacher.common.JwtTokenUtil;
import com.teacher.pojo.enums.PermissionType;
import com.teacher.pojo.json.PermissionList;
import com.teacher.security.entity.permission.Permission;
import com.teacher.security.entity.security.RedisUserInfo;
import com.teacher.security.service.IRedisService;
import com.teacher.service.IPermissionService;
import com.teacher.service.IRoleService;
import com.teacher.pojo.vo.permission.PermissionAddVo;
import com.teacher.pojo.vo.permission.PermissionTreeVo;
import com.teacher.pojo.vo.permission.PermissionUpdateVo;
import com.teacher.pojo.entity.Role;
import com.teacher.mapper.PermissionMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zfm
 * @since 2020-06-02
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {

    @Autowired
    private IRoleService iRoleService;

    @Autowired
    private IRedisService iRedisService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private HttpServletRequest httpServletRequest;

    /**
     * @param permissionAddVo object of permission's value
     * @return add permission whether success
     */
    @Override
    public CommonResult<String> addPermission(PermissionAddVo permissionAddVo) {
        Permission permission = new Permission();
        BeanUtils.copyProperties(permissionAddVo, permission);
        CommonResult<String> commonResult = vailPermission(permission);
        if (commonResult != null) {
            return commonResult;
        }

        if (baseMapper.insert(permission) == 1) {
            return CommonResult.success("添加成功");
        }
        return CommonResult.failed("添加失败");
    }

    /**
     * @param permissionUpdateVo object of permission's value
     * @return update whether success
     */
    @Override
    public CommonResult<String> updatePermission(PermissionUpdateVo permissionUpdateVo) {
        Permission permission = new Permission();
        BeanUtils.copyProperties(permissionUpdateVo, permission);
        CommonResult<String> commonResult = vailPermission(permission);
        if (commonResult != null) {
            return commonResult;
        }
        if (baseMapper.updateById(permission) == 1) {
            return CommonResult.success("更新成功");
        }
        return CommonResult.failed("更新失败");
    }

    /**
     * @return query all permission by tree's shape
     */
    @Override
    public CommonResult<List<PermissionTreeVo>> treePermission() {
        List<Permission> permissionList = baseMapper.selectList(new QueryWrapper<Permission>().lambda()
                .orderByDesc(Permission::getSort));
        // clone of permission to permission by tree's shape
        List<PermissionTreeVo> treeVoList = getPermissionTree(permissionList);
        return CommonResult.success(treeVoList);
    }

    private List<PermissionTreeVo> getPermissionTree(List<Permission> permissionList) {
        List<PermissionTreeVo> treeVoList = new ArrayList<>();
        List<PermissionTreeVo> permissionTreeVoListOri = new ArrayList<>();
        for (Permission permission : permissionList) {
            PermissionTreeVo permissionTreeVo = new PermissionTreeVo();
            BeanUtils.copyProperties(permission, permissionTreeVo);
            permissionTreeVoListOri.add(permissionTreeVo);
        }

        // match parents and children
        for (PermissionTreeVo permissionTreeVo : permissionTreeVoListOri) {
            if (permissionTreeVo.getParentId() == 0) {
                treeVoList.add(permissionTreeVo);
                continue;
            }
            for (PermissionTreeVo treeVo : permissionTreeVoListOri) {
                if (treeVo.getId().equals(permissionTreeVo.getParentId())) {
                    if (treeVo.getChildren() == null) {
                        treeVo.setChildren(new ArrayList<>());
                    }
                    treeVo.getChildren().add(permissionTreeVo);
                }
            }
        }
        return treeVoList;
    }

    /**
     * get permission by role's id
     *
     * @param id
     * @return
     */
    @Override
    public CommonResult<List<String>> getPermissionByRoleId(Long id) {
        // query role's permission

        Role role = iRoleService.getById(id);
        if (role == null) {
            return CommonResult.failed("角色不存在");
        }
        PermissionList permission = JSONUtil.toBean(role.getPermission(), PermissionList.class);
        List<String> belowId = new ArrayList<>();

        // no permission
        if (permission.getPermissionList().size() == 0) {
            return CommonResult.success(belowId);
        }

        List<Permission> permissionList = baseMapper.selectList(new QueryWrapper<Permission>().lambda()
                .in(Permission::getId, permission.getPermissionList()));


        List<PermissionTreeVo> permissionTreeVoList = getPermissionTree(permissionList);
        getBelow(permissionTreeVoList, belowId);


        return CommonResult.success(belowId);
    }

    /**
     * get menu of root
     *
     * @return
     */
    @Override
    public CommonResult<List<Permission> > getRootMenu() {
        RedisUserInfo redisUserInfo = JSONUtil.toBean(iRedisService.get(jwtTokenUtil.getUsernameByRequest(httpServletRequest)), RedisUserInfo.class);
        return CommonResult.success(redisUserInfo.getRootMenu());
    }

    private void getBelow(List<PermissionTreeVo> permissionTreeVoList, List<String> belowId) {
        for (PermissionTreeVo permissionTreeVo : permissionTreeVoList) {
            if (permissionTreeVo.getChildren() == null) {
                belowId.add(String.valueOf(permissionTreeVo.getId()));
            } else {
                getBelow(permissionTreeVo.getChildren(), belowId);
            }
        }
    }

    /**
     * vail permission's type,status and parent'id if exist
     *
     * @param permission object of permission
     * @return
     */
    private CommonResult<String> vailPermission(Permission permission) {
        if (!permission.getType().equals(PermissionType.BUTTON.getCode()) &&
                !permission.getType().equals(PermissionType.MENU.getCode())) {
            return CommonResult.failed("权限类型不正确");
        }
//        if (!permission.getStatus().equals(PermissionStatus.BAN.getCode()) ||
//                !permission.getStatus().equals(PermissionStatus.NORMAL.getCode())) {
//            return CommonResult.failed("权限状态类型不正确");
//        }
        if (baseMapper.selectById(permission.getParentId()) == null && permission.getParentId() != 0) {
            return CommonResult.failed("父级权限不存在");
        }
        return null;
    }

}
